/******************************************************************************/
/*  Class UART1                                                               */
/*  PO: S. Maslyakov, rusoil.9@gmail.com                                      */
/*                                                                            */
/*  Revision:     1.1                                                         */
/*  Date:         2010/12/24 13:37:33                                         */
/******************************************************************************/


#include "data_types.h"
#include "Core\core.h"
#include "Led\led.h"
#include "Modem\modem.h"
#include "TNKernel\tn.h"
#include "Uart\uart1.h"


// Event
static TN_EVENT event_uart;


//==============================================================================
// App: Init uart
//==============================================================================
void UART1::Init_Uart(const uint32_t _baudrate, const uint8_t _key) {
    U1IER = 0UL;                  // int dis

    PCONP_bit.PCUART1 = 1;

    // Tune pins
    PINSEL4_bit.P2_0 = 2;         // TXD
    PINSEL4_bit.P2_1 = 2;         // RXD
    PINSEL4_bit.P2_2 = 2;         // CTS
    PINSEL4_bit.P2_3 = 2;         // DCD
    PINSEL4_bit.P2_4 = 2;         // DSR
    PINSEL4_bit.P2_5 = 2;         // DTR
    PINSEL4_bit.P2_6 = 2;         // RI
    PINSEL4_bit.P2_7 = 2;         // RTS

    FIO2DIR_bit.P2_0 = 1;         // TXD
    FIO2DIR_bit.P2_1 = 0;         // RXD
    FIO2DIR_bit.P2_2 = 0;         // CTS
    FIO2DIR_bit.P2_3 = 0;         // DCD
    FIO2DIR_bit.P2_4 = 0;         // DSR
    FIO2DIR_bit.P2_5 = 1;         // DTR
    FIO2DIR_bit.P2_6 = 0;         // RI
    FIO2DIR_bit.P2_7 = 1;         // RTS

    PINMODE4_bit.P2_0 = 2;        // TXD 0=PULL_UP, 1=RESERVED, 2=PULL_DIS, 3=PULL_DOWN
    PINMODE4_bit.P2_1 = 2;        // RXD
    PINMODE4_bit.P2_2 = 2;        // CTS
    PINMODE4_bit.P2_3 = 2;        // DCD
    PINMODE4_bit.P2_4 = 2;        // DSR
    PINMODE4_bit.P2_5 = 2;        // DTR
    PINMODE4_bit.P2_6 = 2;        // RI
    PINMODE4_bit.P2_7 = 2;        // RTS

    U1LCR = 0x80|_key;             // 8 bits, no Parity, 1 Stop bit
    U1FDR_bit.DIVADDVAL = 0;
    U1FDR_bit.MULVAL = 0;

    uint32_t Br;

    if(_baudrate == 115200UL) {
        // ! for FPCLK=28800000
        U1DLM = 0;
        U1DLL = 13;
        U1FDR_bit.DIVADDVAL = 1;
        U1FDR_bit.MULVAL = 5;
    }
    else {
        Br = (FPCLK / 16) / _baudrate;
        U1DLM = Br / 256;
        U1DLL = Br % 256;
    };

    U1LCR = _key;                 // DLAB = 0

    U1MCR = MCR_DTR|MCR_RTS|MCR_RTSEN|MCR_CTSEN;  // Init modem signals - auto-flow en
    Br = U1MSR;

    U1FCR = 0x81;                 // Enable and reset TX and RX FIFO, size 8 bytes

    // Init rtos event
    Create_uart_event();
}
//==============================================================================
//==============================================================================


//==============================================================================
// App: Rx byte
//==============================================================================
void UART1::RxByte(const uint8_t _data) {
    if(uart.rx.dataLen < UART_BUFF_SIZE) {
        uart.rx.buff[uart.rx.dataLen++] = _data;

        // Set event - new data ready
        tn_event_iset(&event_uart, UART1_RX_EVENT);
    };
}
//==============================================================================
//==============================================================================


//==============================================================================
// App: Rx data
//==============================================================================
void UART1::RxData(const uint8_t * _pData, const uint32_t _dataLen) {
    if(!_dataLen) {
        return;
    };

    for(uint32_t i = 0; i < _dataLen; i++) {
        if(uart.rx.dataLen < UART_BUFF_SIZE) {
            uart.rx.buff[uart.rx.dataLen++] = *_pData++;
        }
        else {
            break;
        };
    };

    // Set event - new data ready
    tn_event_iset(&event_uart, UART1_RX_EVENT);
}
//==============================================================================
//==============================================================================


//==============================================================================
// App: Get rx data
//==============================================================================
uint32_t UART1::GetRxData(uint8_t * const _pBuff) {
    if((uart.rx.dataLen == 0) || (uart.rx.dataLen > UART_BUFF_SIZE)) {
        uart.rx.dataLen = 0;
        return 0;
    };

    uint32_t len = 0;

    while(len < uart.rx.dataLen) {
        _pBuff[len] = uart.rx.buff[len];
        len++;
    };

    uart.rx.dataLen = 0;
    return len;
}
//==============================================================================
//==============================================================================


//==============================================================================
// App: Tx data
//==============================================================================
void UART1::TxData(const uint8_t * const _pData, const uint32_t _dataLen) {

    //if (MODEM::IsTransparent() == FALSE_T) {
    //    DEBUG_PRINTF("%s\r\n", _pData);
    //};

    if(_dataLen) {
        uart.tx.pBuff = _pData;
        uart.tx.dataLen = _dataLen;
        StartTx();
    };

    LED::IntLedOn(eLED_GSM, 0x00010002);
}
//==============================================================================
//==============================================================================


//==============================================================================
// App: Start tx
//==============================================================================
void UART1::StartTx() {
    for(uint32_t i = 0; i < (UART1_FIFO_TRLEVEL * 2); i++) {
        if(uart.tx.dataLen) {
            uart.tx.dataLen--;
            U1THR = *uart.tx.pBuff++;
        }
        else {
            tn_event_set(&event_uart, UART1_TX_EVENT);
            break;
        };
    };
}
//==============================================================================
//==============================================================================


//==============================================================================
// App: Tx byte
//==============================================================================
uint8_t UART1::TxByte() {
    if(uart.tx.dataLen) {
        uart.tx.dataLen--;
        return (*uart.tx.pBuff++);
    };
    return 0;
}
//==============================================================================
//==============================================================================


//==============================================================================
// App: Create uart event
//==============================================================================
void UART1::Create_uart_event() {
    // Event
    event_uart.id_event = 0;
    tn_event_create(&event_uart,                              // Ptr to already existing TN_EVENT
                    TN_EVENT_ATTR_SINGLE|TN_EVENT_ATTR_CLR,   // Attribute event
                    0UL                                       // Pattern initial value
                   );
}
//==============================================================================
//==============================================================================


//==============================================================================
// App: Get uart event
//==============================================================================
void * UART1::Get_uart_event() {
    // Event
    return &event_uart;
}
//==============================================================================
//==============================================================================